<script setup lang="ts">
import "../../utils/vis-network.min.js";
import { onMounted, ref } from "vue";
import {
  getUserServer,
  getUserContainer,
  getUserInfo,
  getVirtualList
} from "@/api/user";
import { portInfo, volumeInfo } from "@/utils/hide";
import { useRouter } from "vue-router";

const router = useRouter();
const networkContainer = ref(null);
const subnet = ref("");

const getUser = async () => {
  const res = await getUserInfo();
  subnet.value = res.data.data.subnet ?? "";
};

const createNodes = (res: any, type: any = "") => {
  return res.data.map((item: any) => ({
    id: item.server_id,
    type: "node",
    connect: "base",
    label: type ? `虚拟机：${item.name}` : `容器：${item.name}`,
    image: type ? "/images/icons/虚拟机节点.png" : "/images/icons/节点.png"
  }));
};

const createUserNetwork = (newNode: any[]) => {
  return newNode.map((item: any, index: number) => ({
    id: index + 100,
    type: "network",
    connect: item.id,
    label: `用户网络\n${subnet.value}`,
    image: "/images/icons/用户网络.png"
  }));
};

const createContainerNodes = (
  containerList: any[],
  userNet: any[],
  type: any = ""
) => {
  return containerList.map((item: any) => {
    const res = userNet.find((it: any) => it.connect === item.server_id);
    if (type) {
      return {
        id: item.id,
        type: "VM",
        connect: res.id,
        label: `虚拟机\n${item.network_ip}`,
        state: item.state,
        image:
          item.state == "2"
            ? "/images/icons/虚拟机.png"
            : "/images/icons/虚拟机关.png"
      };
    } else {
      return {
        id: item.container_id,
        type: "container",
        connect: res.id,
        label: `容器\n${item.container_ip}`,
        state: item.container_state,
        image: item.container_state
          ? "/images/icons/容器.png"
          : "/images/icons/容器关.png"
      };
    }
  });
};

const createNetNodes = (netlist: any[]) => {
  const netNode: any[] = [];
  netlist.forEach((item: any) => {
    if (item.net.length > 0) {
      item.net.forEach((nowitem: any) => {
        const name = getNameByConnectType(nowitem);
        netNode.push({
          id: Math.random(),
          type: nowitem.connect_type,
          connect: item.id,
          label: name,
          image: getImageByConnectType(nowitem.connect_type)
        });
      });
    }
  });
  return netNode;
};

const getNameByConnectType = (nowitem: any) => {
  switch (nowitem.connect_type) {
    case "nginx":
      return `NAT建站\n${nowitem.domain}`;
    case "floating_ip":
      return `浮动IP\n${nowitem.floating_ip}`;
    default:
      return `端口转发\n${nowitem.container_port}:${nowitem.server_port}`;
  }
};

const getImageByConnectType = (connectType: string) => {
  switch (connectType) {
    case "port_forward":
      return "/images/icons/端口转发.png";
    case "floating_ip":
      return "/images/icons/浮动IP.png";
    case "volume":
      return "/images/icons/卷.png";
    case "nginx":
      return "/images/icons/NAT建站.png";
    default:
      return "";
  }
};

const createEdges = (nodes: any[]) => {
  return nodes
    .filter((node: any) => node.connect)
    .map((node: any) => ({ from: node.connect, to: node.id }));
};

onMounted(async () => {
  await getUser();
  const serverRes = await getUserServer();
  const serverResVm = await getUserServer({ server_type: "hyperV" });
  console.log(serverRes, serverResVm, "获取用户容器列表");
  const newNode = createNodes(serverRes);
  const newNodeVm = createNodes(serverResVm, "vm");
  newNode.push(...newNodeVm);
  const userNet = createUserNetwork(newNode);
  const containerRes = await getUserContainer({ page: 1, count: 100 });
  const VmList = await getVirtualList({ page: 1, count: 100 });
  console.log(containerRes, VmList, "获取用户容器列表");
  const containerList = containerRes.data.data;
  const containerListVm = VmList.data.data;
  console.log(containerListVm, containerListVm, "获取用户虚拟机列表");
  const netlist = containerList.map((item: any) => ({
    id: item.container_id,
    net: item.container_connects
  }));
  const netNodeVM = containerListVm.map((item: any) => ({
    id: item.id,
    net: item.port_forwards
  }));
  // 虚拟机数据卷信息
  const Vmvolumes = containerListVm.map((item: any) => ({
    id: item.id,
    data: item.volumes
  }));
  console.log(volumeInfo(Vmvolumes), Vmvolumes, "获取用户虚拟机端口列表");
  const netNode = createNetNodes(netlist);
  netNode.push(...portInfo(netNodeVM), ...volumeInfo(Vmvolumes));
  console.log(netNode, netlist, "获取用户网络列表");
  // 虚拟机数据重组
  const containerNodeVm = createContainerNodes(containerListVm, userNet, "vm");
  // 容器数据重组
  const containerNode = createContainerNodes(containerList, userNet);
  containerNode.push(...containerNodeVm);
  console.log(containerNode, netNode, "列表111");

  const nodes = [...newNode, ...userNet, ...containerNode, ...netNode];
  console.log(nodes, "列表");
  const edges = createEdges(nodes);

  const container = networkContainer.value;
  const data = { nodes, edges };
  const options = {
    nodes: {
      borderWidth: 1,
      borderWidthSelected: 2,
      brokenImage: undefined,
      chosen: true,
      color: {
        border: "#2B7CE9",
        background: "#97C2FC",
        highlight: {
          border: "#2B7CE9",
          background: "#D2E5FF"
        },
        hover: {
          border: "#2B7CE9",
          background: "#D2E5FF"
        }
      },
      opacity: 1,
      fixed: { x: false, y: false },
      font: {
        color: "#343434",
        size: 14,
        face: "arial",
        background: "none",
        strokeWidth: 0,
        strokeColor: "#ffffff",
        align: "center",
        multi: false,
        vadjust: 0,
        bold: {
          color: "#343434",
          size: 14,
          face: "arial",
          vadjust: 0,
          mod: "bold"
        },
        ital: {
          color: "#343434",
          size: 14,
          face: "arial",
          vadjust: 0,
          mod: "italic"
        },
        boldital: {
          color: "#343434",
          size: 14,
          face: "arial",
          vadjust: 0,
          mod: "bold italic"
        },
        mono: {
          color: "#343434",
          size: 15,
          face: "courier new",
          vadjust: 2,
          mod: ""
        }
      },
      group: undefined,
      heightConstraint: false,
      hidden: false,
      icon: {
        face: "FontAwesome",
        code: "\uf0c1",
        weight: "regular",
        size: 50,
        color: "#2B7CE9"
      },
      image: "/images/icons/容器.png",
      imagePadding: { left: 0, top: 0, bottom: 0, right: 0 },
      label: undefined,
      labelHighlightBold: true,
      level: undefined,
      mass: 1,
      physics: true,
      scaling: {
        min: 10,
        max: 30,
        label: {
          enabled: false,
          min: 14,
          max: 30,
          maxVisible: 30,
          drawThreshold: 5
        },
        customScalingFunction: (
          min: number,
          max: number,
          total: number,
          value: number
        ) => {
          if (max === min) return 0.5;
          const scale = 1 / (max - min);
          return Math.max(0, (value - min) * scale);
        }
      },
      shadow: {
        enabled: false,
        color: "rgba(0,0,0,0.5)",
        size: 10,
        x: 5,
        y: 5
      },
      shape: "image",
      shapeProperties: {
        borderDashes: false,
        borderRadius: 6,
        interpolation: false,
        useImageSize: false,
        useBorderWithImage: false
      },
      size: 25,
      title: undefined,
      value: undefined,
      widthConstraint: false
    }
  };

  const network = new vis.Network(container, data, options);

  network.on("doubleClick", (params: any) => {
    const option = params.nodes[0];
    if (option) {
      const node = nodes.find((n: any) => n.id === option);
      if (node?.type === "container") {
        router.push(`/self/container?container_id=${node.id}`);
      } else if (node?.type === "VM") {
        router.push(`/self/vmContainer?container_id=${node.id}`);
      }
    }
  });
});
</script>

<template>
  <div>
    <div id="network" ref="networkContainer" />
  </div>
</template>

<style lang="scss" scoped>
#network {
  width: 100%;
  height: calc(100vh - 20px);
  border: 1px solid lightgray;
  background-color: white;
}
</style>
